package cn.factorybox.item.service.impl;

import cn.factorybox.common.entity.PageResult;
import cn.factorybox.common.utils.IdWorker;
import cn.factorybox.entity.UserInfo;
import cn.factorybox.item.config.CodeCache;
import cn.factorybox.item.config.JwtProperties;
import cn.factorybox.item.mapper.FactoryDeviceDataMapper;
import cn.factorybox.item.mapper.FactoryDeviceMapper;
import cn.factorybox.item.mapper.FactoryJudgeValueMapper;
import cn.factorybox.item.mapper.UserMapper;
import cn.factorybox.item.service.FactoryDeviceDataService;
import cn.factorybox.model.entity.FactoryDevice;
import cn.factorybox.model.entity.FactoryJudgeValue;
import cn.factorybox.model.entity.FactoryDeviceData;
import cn.factorybox.model.entity.User;
import cn.factorybox.utils.JwtUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author flypig
 * @version 1.0
 * @date 2020-09-13 14:50
 */

@Service
public class FactoryDeviceDataServiceImpl implements FactoryDeviceDataService {

    @Autowired
    private FactoryDeviceDataMapper factoryDeviceDataMapper;

    @Autowired
    private FactoryJudgeValueMapper factoryJudgeValueMapper;

    @Autowired
    private FactoryDeviceMapper factoryDeviceMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private IdWorker idWorker;

    private Integer page;
    private Integer size;

    @Override
    public int saveFactoryDeviceData(FactoryDeviceData factoryDeviceData, int count) {
        if (count >= 2) {
            factoryDeviceData.setState("warning");
        } else {
            factoryDeviceData.setState("normal");
        }
        factoryDeviceData.setfCreateTime(new Date());
        return factoryDeviceDataMapper.saveFactoryDeviceData(factoryDeviceData);
    }

    @Override
    public Map<String,Object> selectDataListByRoomIdAndDate(String roomId, String date) {
        List<FactoryDeviceData> dataList = factoryDeviceDataMapper.selectDataList(roomId, date);
        Map<String,Object> data = new HashMap<>();
        data.put("table",dataList);
        data.put("allcount",dataList.size());
        return data;
    }

    @Override
    public List<FactoryDevice> selectAllDeviceDataStatue(HttpServletRequest request) throws Exception {
        String token = request.getHeader("token");
        UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.jwtProperties.getKey());
        String companyId = userInfo.getCompanyId();
        List<FactoryDevice> devices = factoryDeviceMapper.selectAllDevicesForHomePage(companyId);
        for (int i = 0; i < devices.size(); i++) {
            String deviceId = devices.get(i).getId();
            devices.get(i).setDataList(new ArrayList<>());
            devices.get(i).setType("offline");
            // 找出当前设备最新的16条温度数据数组
            if (devices.get(i).isOnline()) {
                devices.get(i).setDataList(factoryDeviceDataMapper.selectTempListOfDevice(deviceId));
                // 找出最新一条数据
                FactoryDeviceData lastest = factoryDeviceDataMapper.selectLastestData(deviceId);
                devices.get(i).setType(lastest.getState());
            }
        }
        return devices;
    }

    @Override
    public List<Map<String, Object>> selectManagerHomeState(HttpServletRequest request) {
        // 先查出所有的主管
        List<User> masters = userMapper.selectAllMasterForManagerHomeState();
        List<Map<String, Object>> result = new ArrayList<>();
        for (User master : masters) {
            Map<String, Object> map = new HashMap<>();
            map.put("master", master.getuName());   // 主管名字
            String companyId = master.getCompanyId();   // 主管所属公司
            List<FactoryDevice> devices = factoryDeviceMapper.selectAllDevicesForHomePage(companyId);
            for (int i = 0; i < devices.size(); i++) {
                String deviceId = devices.get(i).getId();
                devices.get(i).setDataList(new ArrayList<>());
                devices.get(i).setType("offline");
                // 找出当前设备最新的16条温度数据数组
                if (devices.get(i).isOnline()) {
                    devices.get(i).setDataList(factoryDeviceDataMapper.selectTempListOfDevice(deviceId));
                    // 找出最新一条数据
                    FactoryDeviceData lastest = factoryDeviceDataMapper.selectLastestData(deviceId);
                    devices.get(i).setType(lastest.getState());
                }
            }
            map.put("devices", devices);
            result.add(map);
        }
        return result;
    }

    @Override
    public Map<String, Object> getThresholdValue() {
        Map<String, Object> data = new HashMap<>();
        Map<String, Object> item = new LinkedHashMap<>();
        List<FactoryJudgeValue> thresholds = factoryJudgeValueMapper.selectThreshold();
        for (FactoryJudgeValue factoryJudgeValue : thresholds) {
            Map<String, Double> range = new HashMap<>();
            range.put("min", factoryJudgeValue.getMin());
            range.put("max", factoryJudgeValue.getMax());
            item.put(factoryJudgeValue.getLabel(), range);
        }
        data.put("data", item);
        return data;
    }

    @Override
    public Map<String, Object> getNewestData(String fSerialNumber) {
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> newestData = factoryDeviceDataMapper.getNewestData(fSerialNumber);
        if (newestData.isEmpty()) {
            data.put("data", null);
        } else {
            //为了防止返回的数据不正常，对返回的数据进行简单的判断(傻逼算法)
            int k = 0;
            for (Map<String, Object> item : newestData) {
                int i = 0, j = 0;
                for (Map.Entry<String, Object> entry : item.entrySet()) {
                    if ((double) entry.getValue() == 0) {
                        j++;
                    }
                    i++;
                }
                //判断数值为0的个数如果超过5个则数据不正常
                if (i != j && j < 5) {
                    break;
                }
                if (k < newestData.size() - 1) {
                    k++;
                }
            }
            data.put("data", newestData.get(k));
        }
        return data;
    }

    @Override
    public Map<String, Object> getPeak(String fSerialNumber) {
        Map<String, Object> data = new HashMap<>();
        Map<String, Object> topDatas = factoryDeviceDataMapper.getPeak(fSerialNumber);
        data.put("data", topDatas);
        return data;
    }

    @Override
    public Map<String, Object> getChangeCurveData(String fSerialNumber) {
        Map<String, Object> data = new HashMap<>();
        Map<String, Object> params = new HashMap<>();
        Double[] temp = new Double[7];
        Double[] hum = new Double[7];
        Double[] co2 = new Double[7];
        Double[] tvoc = new Double[7];
        Double[] press = new Double[7];
        Double[] o3 = new Double[7];
        Double[] wind = new Double[7];
        Double[] pm25 = new Double[7];
        params.put("fSerialNumber", fSerialNumber);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        for (int i = 6, j = 0; i >= 0; i--, j++) {
            Calendar nowTime = Calendar.getInstance();
            nowTime.add(Calendar.MINUTE, -i * 10);
            Date dateTime = nowTime.getTime();
            String time = sdf.format(dateTime);
            params.put("time", time);
            List<FactoryDeviceData> datas = factoryDeviceDataMapper.getChangeCurveData(params);
            if (datas.size() > 0) {
                temp[j] = datas.get(0).getfTemperature();
                hum[j] = datas.get(0).getfHumidity();
                co2[j] = datas.get(0).getfCarbonDioxide();
                tvoc[j] = datas.get(0).getfTvoc();
                press[j] = datas.get(0).getfPressure();
                o3[j] = datas.get(0).getfO3();
                wind[j] = datas.get(0).getfWind();
                pm25[j] = datas.get(0).getfPm();
            } else {
                //没有数据则设为空
                temp[j] = null;
                hum[j] = null;
                co2[j] = null;
                tvoc[j] = null;
                press[j] = null;
                o3[j] = null;
                wind[j] = null;
                pm25[j] = null;
            }
        }
        data.put("temp", temp);
        data.put("hum", hum);
        data.put("co2", co2);
        data.put("tvoc", tvoc);
        data.put("press", press);
        data.put("o3", o3);
        data.put("wind", wind);
        data.put("pm25", pm25);
        Map<String, Object> map = new HashMap<>();
        map.put("data", data);
        return map;
    }

    @Override
    public Map<String, Object> getSatisfy(String fSerialNumber) {
        String[] names = {"湿度", "温度", "CO2", "tvoc", "压强", "臭氧", "风速", "PM"};
        //先获取今日总数据数
        Double sum = factoryDeviceDataMapper.getSumData(fSerialNumber);
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> items = new ArrayList<>();
        for (String name : names) {
            //查找指定数据的报警条数
            Double abnormalDataSum = factoryDeviceDataMapper.getAbnormalSum(name, fSerialNumber);
            int value = 100 - (int) ((abnormalDataSum / sum) * 100);      //计算满足率
            Map<String, Object> item = new HashMap<>();
            item.put("name", name);
            item.put("value", value);
            items.add(item);
        }
        //计算综合满足率
        //获取今日报警列表的总条数
        Double abnormalSum = factoryDeviceDataMapper.getAllAbSum(fSerialNumber);
        int whole = 100 - (int) ((abnormalSum / (sum * 8)) * 100);
        data.put("items", items);
        data.put("whole", whole);
        return data;
    }

    @Override
    public Map<String, Object> getAbnormalDataList(String fSerialNumber) {
        Map<String, Object> map = new HashMap<>();
        List<List<Object>> data = new ArrayList<>();
        List<Map<String, Object>> abnormalDataList = factoryDeviceDataMapper.getAbnormalDataList(fSerialNumber);
        for (Map<String, Object> abnormalData : abnormalDataList) {
            List<Object> list = new ArrayList<>();
            list.add(abnormalData.get("item"));
            list.add(abnormalData.get("value"));
            list.add(abnormalData.get("time"));
            data.add(list);
        }
        map.put("data", data);
        return map;
    }

    @Override
    public int deleteData(String id) {
        return factoryDeviceDataMapper.delete(id);
    }

    @Override
    public void editThreshold(Map<String, Object> map) {
        //遍历Map，循环插入
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Map<String, Object> range = (Map<String, Object>) entry.getValue();
            range.put("label", entry.getKey());
            factoryDeviceDataMapper.editThreshold(range);
        }
    }

    @Override
    public int judgeData(FactoryDeviceData factoryDeviceData) {
        //先从获取判断范围，这里的操作比较呆，因为每插入一条数据就要查询一次范围，之后考虑将范围缓存起来，或者存在redis中
        int count = 0;
//        List<FactoryJudgeValue> judgeValues = factoryJudgeValueMapper.selectThreshold();
        List<FactoryJudgeValue> judgeValues = CodeCache.thresholdList;  // 这里直接使用内存中缓存的阈值，避免了多次数据库查找
//        System.out.println(judgeValues.get(0));     // 测试是否更新了缓存
        Date date = new Date();
        String type = factoryDeviceData.getiCount();
        if (factoryDeviceData.getfTemperature() < judgeValues.get(0).getMin() || factoryDeviceData.getfTemperature() > judgeValues.get(0).getMax()) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", idWorker.nextId() + "");
            map.put("fSerialNumber", factoryDeviceData.getfSerialNumber());
            map.put("deviceId",factoryDeviceData.getDeviceId());
            map.put("item", "温度");
            map.put("value", factoryDeviceData.getfTemperature());
            map.put("createTime", date);
            factoryDeviceDataMapper.addAbnormal(map);
            count++;
        }
        if (factoryDeviceData.getfHumidity() < judgeValues.get(1).getMin() || factoryDeviceData.getfHumidity() > judgeValues.get(1).getMax()) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", idWorker.nextId() + "");
            map.put("fSerialNumber", factoryDeviceData.getfSerialNumber());
            map.put("deviceId",factoryDeviceData.getDeviceId());
            map.put("item", "湿度");
            map.put("value", factoryDeviceData.getfHumidity());
            map.put("createTime", date);
            factoryDeviceDataMapper.addAbnormal(map);
            count++;
        }
        if (factoryDeviceData.getfCarbonDioxide() > judgeValues.get(2).getMax()) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", idWorker.nextId() + "");
            map.put("fSerialNumber", factoryDeviceData.getfSerialNumber());
            map.put("deviceId",factoryDeviceData.getDeviceId());
            map.put("item", "CO2");
            map.put("value", factoryDeviceData.getfCarbonDioxide());
            map.put("createTime", date);
            factoryDeviceDataMapper.addAbnormal(map);
            count++;
        }
        if (factoryDeviceData.getfTvoc() > judgeValues.get(3).getMax()) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", idWorker.nextId() + "");
            map.put("fSerialNumber", factoryDeviceData.getfSerialNumber());
            map.put("deviceId",factoryDeviceData.getDeviceId());
            map.put("item", "tvoc");
            map.put("value", factoryDeviceData.getfTvoc());
            map.put("createTime", date);
            factoryDeviceDataMapper.addAbnormal(map);
            count++;
        }
        if (factoryDeviceData.getfPressure() < judgeValues.get(4).getMin() || factoryDeviceData.getfPressure() > judgeValues.get(4).getMax()) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", idWorker.nextId() + "");
            map.put("fSerialNumber", factoryDeviceData.getfSerialNumber());
            map.put("deviceId",factoryDeviceData.getDeviceId());
            map.put("item", "压强");
            map.put("value", factoryDeviceData.getfPressure());
            map.put("createTime", date);
            factoryDeviceDataMapper.addAbnormal(map);
            count++;
        }
        if (type.equals("7") && factoryDeviceData.getfO3() > judgeValues.get(5).getMax()) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", idWorker.nextId() + "");
            map.put("fSerialNumber", factoryDeviceData.getfSerialNumber());
            map.put("deviceId",factoryDeviceData.getDeviceId());
            map.put("item", "臭氧");
            map.put("value", factoryDeviceData.getfO3());
            map.put("createTime", date);
            factoryDeviceDataMapper.addAbnormal(map);
            count++;
        }
        if (type.equals("7") && factoryDeviceData.getfWind() < judgeValues.get(6).getMin() || factoryDeviceData.getfWind() > judgeValues.get(6).getMax()) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", idWorker.nextId() + "");
            map.put("fSerialNumber", factoryDeviceData.getfSerialNumber());
            map.put("deviceId",factoryDeviceData.getDeviceId());
            map.put("item", "风速");
            map.put("value", factoryDeviceData.getfWind());
            map.put("createTime", date);
            factoryDeviceDataMapper.addAbnormal(map);
            count++;
        }
        if (factoryDeviceData.getfPm() > judgeValues.get(7).getMax()) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", idWorker.nextId() + "");
            map.put("fSerialNumber", factoryDeviceData.getfSerialNumber());
            map.put("deviceId",factoryDeviceData.getDeviceId());
            map.put("item", "PM");
            map.put("value", factoryDeviceData.getfPm());
            map.put("createTime", date);
            factoryDeviceDataMapper.addAbnormal(map);
            count++;
        }
        return count;
    }

    @Override
    public Map<String, Object> selectOneDeviceData(Map<String, Object> map) {
        this.page = Integer.parseInt((String) map.get("page"));
        this.size = Integer.parseInt((String) map.get("size"));
        PageHelper.startPage(this.page, this.size);
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> dataList = factoryDeviceDataMapper.selectOneDeviceData(map);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(dataList);
        data.put("data", new PageResult<>(pageInfo.getTotal(), pageInfo.getList()));
        return data;
    }

    @Override
    public int deleteAbnormalData(String id) {
        return factoryDeviceDataMapper.deleteAbnormalData(id);
    }

    @Override
    public Map<String, Object> getAbnormalMessageList(Map<String, Object> map) {
        this.page = Integer.parseInt((String) map.get("page"));
        this.size = Integer.parseInt((String) map.get("size"));
        PageHelper.startPage(this.page, this.size);
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> abnormalMessageList = factoryDeviceDataMapper.getAbnormalMessageList(map);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(abnormalMessageList);
        data.put("data", new PageResult<>(pageInfo.getTotal(), pageInfo.getList()));
        return data;
    }

    @Override
    public void updateThreshold(FactoryJudgeValue factoryJudgeValue) {
        factoryJudgeValueMapper.updateThreshold(factoryJudgeValue);
        // 更新内存中缓存的阈值
        CodeCache.thresholdList = factoryJudgeValueMapper.selectThreshold();
    }
}
